/**
 * 32-bit封装类
 */
export class Bits {

    readonly bits: number[] = [];


    get length() {
        return this.bits.length;
    }

    /**
     * 重置为0
     */
    reset() {
        this.bits.length = 0;
        return this;
    }

    /**
     * 获取bits某一位上的值 0|1
     * @param idx
     */
    getBit(idx: number) {
        if (idx < 0) {
            return 0;
        }
        if (idx < 32) {
            const val = this.bits[0];
            if (val) {
                return val & (1 << idx) ? 1 : 0;
            }
            return 0;
        }
        const bitsIdx = (idx / 32) >>> 0;
        const val = this.bits[bitsIdx];
        if (val) {
            return val & (1 << idx % 32) ? 1 : 0;
        }
        return 0;
    }

    /**
     * 设置bits上某一位为1或0
     * @param idx 位
     * @param val true:1 false:0
     */
    setBit(idx: number, val: any) {
        if (idx < 0) {
            return this;
        }

        if (idx < 32) {
            if (val) {
                if (this.bits[0] === undefined) {
                    this.bits[0] = 1 << idx;
                } else {
                    this.bits[0] |= 1 << idx;
                }
            } else if (this.bits[0]) {
                this.bits[0] &= ~(1 << idx);
            }
            return this;
        }

        const bitsIdx = idx / 32 >>> 0;
        if (val) {
            if (this.bits[bitsIdx] === undefined) {
                this.bits[bitsIdx] = 1 << idx % 32;
            } else {
                this.bits[bitsIdx] |= 1 << idx % 32;
            }
        } else if (this.bits[bitsIdx]) {
            this.bits[bitsIdx] &= ~(1 << idx % 32);
        }
        return this;
    }

    /**
     * 获取第几个bits的值
     * @param idx
     */
    getBits(idx: number) {
        return this.bits[idx] || 0;
    }

    /**
     * 设置第几个bits的值
     * @param idx
     * @param val
     */
    setBits(idx: number, val: number) {
        this.bits[idx] = val;
        return this;
    }

    /**
     * 是否与目标bits相等
     * @param bits 
     */
    equals(bits: Bits) {
        const len = Math.max(this.length, bits.length);
        for (let i = 0; i < len; ++i) {
            if (this.getBits(i) !== bits.getBits(i)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 当前bits是否包含目标bits
     * @param bits
     */
    include(bits: Bits) {
        const len = Math.max(this.length, bits.length);
        for (let i = 0; i < len; ++i) {
            if ((this.getBits(i) & bits.getBits(i)) !== bits.getBits(i)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 当前bits是否包含目标bits其中一位
     * @param bits
     */
    includeOne(bits: Bits) {
        const len = Math.min(this.length, bits.length);
        for (let i = 0; i < len; ++i) {
            if ((this.getBits(i) & bits.getBits(i)) > 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 从数组中读取
     * @param bits
     */
    fromArray(bits: number[]) {
        this.bits.length = bits.length;
        for (let i = 0; i < bits.length; ++i) {
            this.bits[i] = bits[i];
        }
        return this;
    }

    /**
     * 转化成 bits1-bits2-bits3-bits4 格式的字符串
     * @param 进制
     */
    toString(radix = 2) {
        let key = "";
        if (this.length > 0) {
            const len = this.length - 1;
            for (let i = 0; i < len; ++i) {
                key += (this.bits[i]?.toString(radix) || "0") + "-";
            }
            key += this.bits[this.length - 1]?.toString(radix) || "0";
        }
        return key;
    }
}
